﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BuildServer.Models;

namespace BuildServer.Controllers
{
    [Authorize]
    public class ScheduleController : Controller
    {
        private BuildServerDbContext db = new BuildServerDbContext();

        //
        // GET: /Schedule/Create
        public ActionResult Index()
        {
            // left outer join
            db.Database.Log = (msg) => System.Diagnostics.Trace.WriteLine(msg);
            var query = from def in db.BuildDefinitions
                        join run in db.BuildRuns on def.Id equals run.BuildDefinitionId into tmp
                        from tmprun in tmp.DefaultIfEmpty()
                        select new ScheduleViewModel { Definition = def, Run = tmprun, Template = def.BuildTemplate };
            return View(query);
        }

        //
        // POST: /Schedule/Schedule
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Schedule(int[] buildDefinitions, string targets)
        {
            if (buildDefinitions == null || string.IsNullOrEmpty(targets))
                return RedirectToAction("Index", "Build");

            // check for existing build definition ids
            int[] checkedBuildDefIds = db.BuildDefinitions.Where(x => buildDefinitions.Contains(x.Id)).Select(x => x.Id).ToArray();

            foreach(int buildDefId in checkedBuildDefIds)
            {
                // get existing build run
                var buildRun = db.BuildRuns.FirstOrDefault(x => x.BuildDefinitionId == buildDefId);
                // create new build run if there is none
                if (buildRun == null)
                {
                    buildRun = new BuildRun();
                    buildRun.BuildDefinitionId = buildDefId;
                    db.BuildRuns.Add(buildRun);
                }
                // schedule build run
                buildRun.DoSchedule();
                buildRun.Targets = targets;
                
                // unschedule if no target is specified
                if (targets == "None")
                    buildRun.Scheduled = null;
            }
            db.SaveChanges();

            try
            {
                // notify build server
                using (var tcpClient = new System.Net.Sockets.TcpClient())
                {
                    tcpClient.Connect(System.Net.IPAddress.Loopback, 1724);
                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes("Build");
                    using (var stream = tcpClient.GetStream())
                    {
                        stream.Write(buffer, 0, buffer.Length);
                    }
                    tcpClient.Close();
                }
            }
            catch (Exception ex)
            {
                ViewBag.ErrorMessage = "Build Service could not be notified. Make sure the Build Service is running.";
            }

            return RedirectToAction("Index", "Build");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}